using System;
using L=Science.Physics.GeneralPhysics;

namespace Serway.Chapter10
{
	/// <summary>
	/// Example13: Atwood's Machine Revisited
	/// Two blocks having masses m_1 and m_2 are connected to each 
	/// other by a light cord that passes over two identical 
	/// frictionless pulleys, each having a moment of inertia
	/// I and radius R, as shown in Figure 10.21a. 
	/// Find the acceleration of each block and the tensions T_1, 
	/// T_2 and T_3 in the cord. 
	/// (Assume no slipping between cord and pulleys.)
	/// a = (m_1 - m_2)g/(m_1+m_2+2(I/R^2))
	/// </summary>
	public class Example13
	{
		public Example13()
		{
		}
		private string result;
		public string Result
		{
			get{return result;}
		}
		public void Compute()
		{
			double g = L.Constant.AccelerationOfGravity;

			L.Mass[] m = new L.Mass[2];
			L.TotalForce[] f = new L.TotalForce[2]; 			
			L.Acceleration[] a = new L.Acceleration[2];

			L.MomentOfInertia[] I = new L.MomentOfInertia[2];
			L.TotalTorque[] t = new L.TotalTorque[2];
			L.AngularAcceleration[] alpha = new L.AngularAcceleration[2];

			L.Position[] R = new L.Position[4];
				
			m[0] = new L.Mass();
			m[0].kg = 10.0;
			m[1] = new L.Mass();
			m[1].kg = 40.0;
				
			L.Force[] ff = new L.Force[2];
			ff[0] = new L.Force();  // tension
			ff[0].ZVariableQ = true;
			ff[1] = new L.Force();
			ff[1].Z = -m[0].kg*g;
			f[0] = new L.TotalForce(ff);

			L.Force[] fff = new L.Force[2];
			fff[0] = new L.Force();  // tension
			fff[0].ZVariableQ = true;
			fff[1] = new L.Force();
			fff[1].Z = -m[1].kg*g;
			f[1] = new L.TotalForce(fff);

			a[0] = new L.Acceleration();
			a[0].ZVariableQ = true; 
			a[1] = new L.Acceleration();
			a[1].ZVariableQ = true; 

			I[0] = new L.MomentOfInertia();
			I[0].XX = 3.5;
			I[1] = new L.MomentOfInertia();
			I[1].XX = 3.5;


			L.Torque[] tau = new L.Torque[2];
			tau[0] = new L.Torque();
			tau[0].XVariableQ = true;
			tau[1] = new L.Torque();
			tau[1].XVariableQ = true;
			t[0] = new L.TotalTorque(tau);		
	
			L.Torque[] ttau = new L.Torque[2];
			ttau[0] = new L.Torque();
			ttau[0].XVariableQ = true;
			ttau[1] = new L.Torque();
			ttau[1].XVariableQ = true;
			t[1] = new L.TotalTorque(ttau);	
			
			alpha[0] = new L.AngularAcceleration();
			alpha[0].XVariableQ = true; 
			alpha[1] = new L.AngularAcceleration();
			alpha[1].XVariableQ = true; 

			R[0] = new L.Position();
			R[0].Y = -5.0;
			R[1] = new L.Position();
			R[1].Z = 5.0;
			R[2] = new L.Position();
			R[2].Z = 5.0;
			R[3] = new L.Position();
			R[3].Y = 5.0;

			L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero[] cf
				= new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero[6];
			cf[0] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min0);
			cf[1] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min1);  
			cf[2] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min2);
			cf[3] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min3);  
			cf[4] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min4);
			cf[5] = new L.NewtonEquationInvolvingTorque.ConstraintFunctionToBeZero(Min5);  
		
			L.NewtonEquationInvolvingTorque eq 
				= new L.NewtonEquationInvolvingTorque(f,m,a,t,I,alpha,R);			
			eq.Constraint(cf);

			eq.Solve();
		
			result += Convert.ToString(alpha[0].X)+"\r\n";
			result += Convert.ToString(alpha[1].X)+"\r\n";

			result += Convert.ToString(a[0].Z)+"\r\n";
			result += Convert.ToString(g*(m[1].kg-m[0].kg)/(m[0].kg+m[1].kg+2.0*I[0].XX/R[0].Y/R[0].Y))+"\r\n";
		}
		private double Min0(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return f[0].DecomposedForce[0].Z*radius[0].Y + tau[0].DecomposedTorque[1].X;
		}
		private double Min1(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return f[1].DecomposedForce[0].Z*radius[3].Y + tau[1].DecomposedTorque[1].X;
		}
		private double Min2(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return tau[0].DecomposedTorque[0].X + tau[1].DecomposedTorque[0].X;
		}
		private double Min3(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return alpha[0].X - a[0].Z/radius[0].Y;
		}
		private double Min4(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return alpha[1].X - alpha[0].X;
		}
		private double Min5(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a,
			L.TotalTorque[] tau, L.MomentOfInertia[] I, L.AngularAcceleration[] alpha, L.Position[] radius)
		{
			return a[0].Z + a[1].Z;
		}
	}
}
